Module# 02: Generic Programming              Lecture#05: Bounded Argument Generic Classes

 

// Example 5.1: Why bounding of types in generic class definition?

 

GenericError<T> {

     T[ ] array;           // An array of type T

     // Pass the constructor a reference to  an array of type T.

     GenericError (T[ ] t) {

          array = t;

     }

       

       double average() {   // Return type double in all cases

        double sum = 0.0;

        for(int i=0; i < array.length; i++)

          sum += array[i].doubleValue(); // Here is compiler error!

        return sum / array.length;

     }

}     

 

 

// Example 5.2 : Upper bound of argument in generic class definition

 

GenericBound<T extends Number > {

     T[ ] array;     // an array of type T

  

     // Pass the constructor a reference to  an array of type T.

     GenericBound (T[ ] t) {

           array = t;

     }

 

     double average() {   // Return type double in all cases

          double sum = 0.0;

          for(int i=0; i < array.length; i++)

             sum += array[i].doubleValue();     // Now, it is okay

          return sum / array.length;

     }

}

 

class GenericBoundDemo {

      public static void main(String args[]) {

            Integer intArray[] = { 1, 2, 3, 4, 5 };

            GenericBound <Integer> intData = new GenericBound

                                                  <Integer>(intArray);

            double avgInt = intData.average();

            System.out.println("Average is " + avgInt);

 

            Double doubleArray[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };

            GenericBound <Double> doubleData = new GenericBound

                                                <Double>(doubleArray);

            double abgDouble = doubleData.average();

            System.out.println("Average is " + avgDouble);

 

            String strArray[] = { "1", "2", "3", "4", "5" };

            GenericBound <String> strData = new GenericBound        

                                                   <String>(strArray);

      /*

             double avgStr = strData.average();     // ERROR!

             System.out.println("Average is " + avgStr);                   */                        

      }

}

 

// Example 5.3: Generic class with another limitation

 

class Student<T extends Number>{

    String name;

    T [ ] marks;     // To store the marks obtained by a student

            // The usual constructor for the generic class Student

    Student (T [ ] m) {

       marks = m;

    }

    // This method to calculate the total of marks obtained by a student

    double total( ) {

      double sum = 0.0;

      for(int i = 0; i < marks.length; i++)

        sum += marks[i].doubleValue();

      return (sum);

    }

 

// This method compares the marks obtained by this

     // student with another student

     boolean compareMarks(Student<T>  others) {

      if ( total() == others.total() )

         return true;

      return false;

     }

}      // End of the generic class definition

 

// Driver class while instantiating the Student generic class with different number format.

class GenericLimitationDemo {

    public static void main(String args[])      {

        Integer intMarks1[] = { 44, 55, 33, 66, 77 };     // Marks stored in integer for s1

        Student<Integer> s1IntMarks = new Student<Integer>(intMarks1);

        System.out.println("Total marks " + s1IntMarks.total());

                       

        Integer intMarks2[] = { 49, 39, 53, 69 };     // Marks stored in integer for s2

        Student<Integer> s2IntMarks = new Student<Integer>(intMarks2);

        System.out.println("Total marks " + s2IntMarks.total());

       // Compare marks between s1 and s2

       if (s1IntMarks.compareMarks (s2IntMarks))

      System.out.println("Same marks");

       else

      System.out.println("Different marks.");

Double doubleMarks[] = { 43.5, 55.5, 32.5, 66.5, 77.0 };   // Marks stored in double for s3

       Student<Double> s3DoubleMarks = new Student<Double>(doubleMarks);

       System.out.println("Total marks " + s3DoubleMarks.total());

                       

       Float floatMarks[] = { 50.0F, 40.0F, 60.0F, 65.0F };     // Marks stored in float for s4

       Student<Float> s4FloatMarks = new Student<Float>(floatMarks);

       System.out.println("Total marks " + s4FloatMarks.total());

       // Compare marks between s2 and s3

       if (s2IntMarks.compareMarks (s3DoubleMarks))       // ERROR!

      System.out.println("Same marks");

       else

      System.out.println("Different marks.");

       // Compare marks between s3 and s4

       if (s3DoubleMarks.compareMarks (s4FloatMarks))    // ERROR!

      System.out.println("Same marks");

       else

      System.out.println("Different marks.");

      }

}

 

 

// Example 5.4: Generic class with wildcard argument

 

class Student <T extends Number>{

    String name;

    T [ ] marks;     // To store the marks obtained by a student

            // The usual constructor for the generic class Student

    Student (T [ ] m) {

       marks = m;

    }

    // This method to calculate the total of marks obtained by a student

    double total( ) {

      double sum = 0.0;

      for(int i = 0; i < marks.length; i++)

        sum += marks[i].doubleValue();

      return (sum);

    }

 

// This method compares the marks obtained by this

     // student with another student

     boolean compareMarks(Student<?>  others) {

      if ( total() == others.total() )

         return true;

      return false;

     }

}      // End of the generic class definition

 

 

// Example 5.5: Definition of all the classes in of animals

 

class Animal {

    long lifespan;

    float weigh;

    Animal(long years, float kg) {

        lifespan = years;

                weight = kg;

    }

 

    public void print( ) {

        System.out.println(“Maximum longevity:+ lifespan +  in years”);

        System.out.println(“Maximum weight:   + weight +  in kgs”);

   }

}   // End of class Animal

 

class Aquatic extends Animal {

      boolean scale;         // true: has scale, false: no scale

      Aquatic(long years, float kg, boolean skin) {

            super(years, kgs);              // Super class constructor

             scale = skin;

        }

 

        public void print( ) {

             super.print();   // Call the super class method

             System.out.println(“Has scale?     + scale);

       }

}   // End of class Aquatic

 

class Land extends Animal {

      short vision;   //0 = nocturnal, 1 = only day light,  2 = both

      Land(long years, float kg, short vision) {

           super(years, kgs);              // Super class constructor

           this.vision = vision;

     }

}   // End of class Land

 

class Pet extends Land {

      String name;

      Pet(long years, float kg, short vision, String name) {

          super(years, kgs, vision, name);   // Super class constructor

             this.name = name;

      }

}   // End of class Pet

 

class Wild extends Land {

      float speed;  // Maximum running speed in mph

      Wild(long years, float kg, short vision, float speed) {

          super(years, kgs, vision, name);  // Super class constructor

          this.speed = speed;

     }

}   // End of class Wild

 

// Defining a generic class to maintain list of all animals

class AnimalWorld<T extends Animal> {          

     //Type parameter is limited to Animal and its sub classes

     T [ ] listOfAnimals;

 

     AnimalWorld(T [ ] list)  // Generic constructor to create a list of type T

            listOfAnimals = list;

     }

}   // End of the generic class AnimalWorld

 

// Defining different methods with different bounds of arguments

class BoundedWildcards {

 

//Case 1: Unbound wildcard: Any object can be passed as its argument. 

   static void vitality(AnimalWorld<?> animals) {

        //To print the vitality of animals in the list of animals

        for(Animal a : animals)

            a.print();

        System.out.println();

   }

 

// Case 2: Lower bounded wildcard: Any object of Aquatic or Animal can // be passed as its argument.

 

     static void showSea(AnimalWorld<?  super Aquatic> animals) {

          //For aquatic or unknown animals

          for(Object obj : animals)

              obj.print();     

                   // Call the method defined in Animal/ Aquatic class

          System.out.println();

     }

// Case 3a: Upper bounded wildcard: Any object of Land/ Pet/ Wild can // be passed as its argument.

 

     static void showLand(AnimalWorld<?  extends Land> animals) {

         //For Land or any of its subclasses

         for(int i = 0; i < animals.listOfAnimals.length)  {

             animals.listOfAnimals[i].print();     

                 // Call the method defined in Animal class

             System.out.println(“Vision :+

                                     animals.listOfAnimals[i].vision);

          }

          System.out.println();

     }

 

// Case 3b: Upper bounded wildcard: Any object of only  Pet class can // be passed as its argument.

 

       static void showPet(AnimalWorld<?  extends Pet> animals) {

            //For lists of Pet objects only

            for(int i = 0; i < animals.listOfAnimals.length)  {

                 System.out.println(“Pet’s name:+

                 animals.listOfAnimals[i].name);

                 animals.listOfAnimals[i].print();     

                 // Call the method defined in Animal class

                 System.out.println(“Vision :+

                                         animals.listOfAnimals[i].vision);

            }

            System.out.println();

        }

 

// Case 3c: Upper bounded wildcard: Any object of only  Wild class can // be passed as its argument.

 

       static void showWild(AnimalWorld<?  extends Wild> animals) {

            //For objects of Wild class only

            for(int i = 0; i < animals.listOfAnimals.length)  {

                animals.listOfAnimals[i].print();     

                           // Call the method defined in Animal class

                System.out.println(“Maximum running speed:+

                          animals.listOfAnimals[i].speed + “ in mph”);

                System.out.println(“Vision :+

                          animals.listOfAnimals[i].vision);

            }

            System.out.println();

        }

}  // End of the method definitions in class BoundedWildcards

 

class BoundedWildcardArgumentsDemo {

    public static void main(String args[]) {

 

        // Create a list of unknown animals of class Animal

        Animal unknown = new Animal(40, 720);    

                               // An unknown animal object is created

        Animal u [] = {unknown};      // Array of unknown animals

        AnimalWorld<Animal> uList = new AnimalWorld<Animal>(u);    

                                     // Place the unknown into a list

 

        // Create a list of aquatic animals

        Aquatic whale = new Aquatic(90, 150000);    

                                     // A whale object is created

        Aquatic shark = new Aquatic(400, 2150);    

                                     // A shark object is created

        Animal q [] = { whale, shark };     

                                     // Array of aquatic animals

        AnimalWorld<Aquatic> qList = new AnimalWorld<Aquatic>(q);

                                    // Place the aquatics into a list

// Create a list of land animals

        Land owl = new Land(3, 1, 0);    

                                      // A land owl object is created

        Land l [] = { owl };    // An array of land objects is created

        AnimalWorld<Land> lList = new AnimalWorld<Land>(l);    

                                         // Place the animals into a list

 

        // Create a list of pet animals

        Pet dog = new Pet(15, 75, 2, “Prince”);    

                                // A pet dog object is created

        Pet p [] = { new Pet(15, 75, 2, “Prince”) };    

                                // An array of pet objects is created

            AnimalWorld<Pet> pList = new AnimalWorld<Pet>(p);    

                                // Place the pets into a list

// Create a list of wild animals

       Wild cheetah = new Land(15, 75, 2);    

                               // A cheetah object is created

       Wild deer = new Land(10, 50, 1);    

                               // A deer object is created            

       Wild w [] = { cheetah, deer };     

                               // Array of non-aquatic animals

       AnimalWorld<Wild> wList = new AnimalWorld<Wild>(w);    

                         // Place the wilds into a list

 

// Call the methods and see the outcomes

            // vitality(…) is with unlimited wildcard argument and

            // hence we can pass argument of any type

            vitality (uList);      // OK

            vitality (qList);     // OK

            vitality (lList);    // OK

            vitality (pList);   // OK

            vitality (wList);  // OK

 

// showSea(…) is with lower bound wildcard argument with

            // class Aquatic and its super classes

            showSea (uList);      // OK

            showSea (qList);     // OK

            showSea (lList);    // Compile-time error

            showSea (pList);   // Compile-time error

            showSea (wList);  // Compile-time error

 

// showLand(…) is with upper bound wildcard argument with

           // class Land and its subclasses

            showLand (uList);      // Compile-time error

            showLand (qList);     // Compile-time error

            showLand (lList);    // OK

            showLand (pList);   // OK

            showLand (wList);  // OK

 

// showPet(…) is with upper bound wildcard argument with

            // class Pet and its subclasses

            showPet (uList);       // Compile-time error

            showPet (qList);      // Compile-time error

            showPet (lList);     // Compile-time error

            showPet (pList);    // OK

            showPet (wList);   // Compile-time error

 

// showWild(…) is with upper bound wildcard argument with

           // class Wild and its sub classes

            showWild (uList);      // Compile-time error

            showWild (qList);     // Compile-time error

            showWild (lList);    // Compile-time error

            showWild (pList);   // Compile-time error

            showWild (wList);  // OK

      }

}